﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using TSOL.FastSPWeb.ValueObjects;
using TSOL.FastSPWeb.Core;

namespace TSOL.FastSPWeb
{
    public static partial class FastSPWebCallExtensions
    {
        public enum CachePolicy { NoCache, FastSPDefault }

        public static void FastItems(this SPList List, CachePolicy cachePolicy, Action<SPListItemCollection> outProc)
        {
            if (cachePolicy == CachePolicy.FastSPDefault)
            {
                Guid SiteGuid = List.ParentWeb.Site.ID;
                Guid WebGuid = List.ParentWeb.ID;
                SPUser CurrentSPUser = List.ParentWeb.CurrentUser;

                var hashKey = (SiteGuid.ToString() + WebGuid.ToString() + List.ID.ToString() + true.ToString() + CurrentSPUser.ID.ToString()).GetHashCode();

                SPItemsCacheCollection _SPItemsCacheCollection = null;
                SPItemsCacheEntity _ItemsCache = null;

                while (_ItemsCache == null)
                {
                    while (!FastSPWebThreadWorkerQueue.GlobalSPWebThreadWorkerQueue.ItemsCacheDictionary.TryGetValue(hashKey, out _SPItemsCacheCollection))
                    {
                        _SPItemsCacheCollection = new SPItemsCacheCollection()
                        {
                            UserUniqueID = CurrentSPUser.ID.ToString(),
                            SiteGuid = SiteGuid,
                            WebGuid = WebGuid,
                            ListGuid = List.ID,
                            MaxCopiesOfElevatedItems = List.ParentWeb.Site.SystemAccount.UserToken.CompareUser(CurrentSPUser.UserToken) ?
                                                FastSPWebThreadWorkerQueue.GlobalSPWebThreadWorkerQueue.MaxCopiesOfElevatedItems :
                                                -1
                        };
                        FastSPItemsFactoryThread.FastSPItemsFactoryThreadTask(List, CurrentSPUser.UserToken, hashKey, _SPItemsCacheCollection);
                    }

                    if (_SPItemsCacheCollection.Count() == 0) FastSPItemsFactoryThread.FastSPItemsFactoryThreadTask(List, CurrentSPUser.UserToken, hashKey, _SPItemsCacheCollection);

                    _ItemsCache = _SPItemsCacheCollection.FirstOrDefault(a => a.Free == true);
                    if (_ItemsCache != default(SPItemsCacheEntity))
                        break;
                    else
                    {
                        lock (_SPItemsCacheCollection) _SPItemsCacheCollection.WaitingForFreeItems++;
                        FastSPWebThreadWorkerQueue.GlobalSPWebThreadWorkerQueue.FastSPItemsWaitingForFreeCacheEntity++;
                    }
                }
                lock (_ItemsCache)
                {
                    try
                    {
                        _ItemsCache.Free = false;
                        outProc(_ItemsCache.Items);
                        _ItemsCache.LastUsed = DateTime.Now;
                    }
                    catch
                    {
                        throw;
                    } finally 
                    {
                        _ItemsCache.Free = true;
                    }
                }
            }
            else
            {
                outProc(List.Items);
            }
        }
    }
}